home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / Terminal 2.2 / Project / Sources / MacBinary.c < prev    next >
Text File  |  1992-01-17  |  13KB  |  566 lines

  1. /*
  2.     Terminal 2.2
  3.     "MacBinary.c"
  4. */
  5.  
  6. #ifdef THINK_C
  7. #include "MacHeaders"
  8. #endif
  9. #ifdef applec
  10. #pragma load ":(Objects):MacHeadersMPW"
  11. #pragma segment Main2
  12. #endif
  13.  
  14. #include "MacBinary.h"
  15. #include "CRC.h"
  16. #include "Utilities.h"
  17.  
  18. #if 1
  19.  
  20. typedef struct {
  21.     Byte b[BinHeaderLength];
  22. } HEADER;
  23. #define HEADER_oldVersion        (header->b)[  0]
  24. #define HEADER_name                (header->b)[  1]
  25. #define HEADER_info1            (header->b)[ 65]
  26. #define HEADER_protected        (header->b)[ 81]
  27. #define HEADER_zero1            (header->b)[ 82]
  28. #define HEADER_dLength            (header->b)[ 83]
  29. #define HEADER_rLength            (header->b)[ 87]
  30. #define HEADER_creation            (header->b)[ 91]
  31. #define HEADER_modification        (header->b)[ 95]
  32. #define HEADER_getInfoLength    (header->b)[ 99]
  33. #define HEADER_info2            (header->b)[101]
  34. #define HEADER_filesLength        (header->b)[116]
  35. #define HEADER_sHeaderLength    (header->b)[120]
  36. #define HEADER_newVersion        (header->b)[122]
  37. #define HEADER_minimumVersion    (header->b)[123]
  38. #define HEADER_crc                (header->b)[124]
  39. #define HEADER_zero3            (header->b)[126]
  40.  
  41. #else    /* This no longer works correctly for THINK C 5.02 */
  42.  
  43. typedef struct {
  44.     Byte oldVersion;        /* 000: Must be zero for compatibility */
  45.     Byte name[64];            /* 001: Pascal string */
  46.     Byte info1[16];            /* 065: Original Finder info: */
  47.                             /*        File type (long) */
  48.                             /*        File creator (long) */
  49.                             /*        Flags (word, low byte must be zero) */
  50.                             /*        File's location (Point) */
  51.                             /*        File's window (short) */
  52.     Byte protected;            /* 081: Low order bit */
  53.     Byte zero1;                /* 082: Must be zero for compatibility */
  54.     Byte dLength[4];        /* 083: Data fork length (in bytes) */
  55.     Byte rLength[4];        /* 087: Resource fork length (in bytes) */
  56.     Byte creation[4];        /* 091: Creation date */
  57.     Byte modification[4];    /* 095: Modification date */
  58.     Byte getInfoLength[2];    /* 099:    Get info length */
  59.     Byte info2;                /* 101: Finder flags, low byte */
  60.     Byte zero2[14];            /* 102: Not used */
  61.     Byte filesLength[4];    /* 116: Length of total unpacked files */
  62.     Byte sHeaderLength[2];    /* 120: Length of secondary header */
  63.     Byte newVersion;        /* 122: Uploading program version number */
  64.     Byte minimumVersion;    /* 123: Minimum version number needed */
  65.     Byte crc[2];            /* 124: CRC of previous 124 bytes */
  66.     Byte zero3[2];            /* 126: Not used */
  67. } HEADER;
  68.  
  69. #endif
  70.  
  71. #define DESKTOP        0x0001    /* ---- ---- ---- ---1 */
  72. #define    COLOR        0x000E    /* ---- ---- ---- 111- */
  73. #define INITED        0x0100    /* ---- ---1 ---- ---- */
  74. #define CHANGED        0x0200    /* ---- --1- ---- ---- */
  75. #define BUSY        0x0400    /* ---- -1-- ---- ---- */
  76. #define BOZO        0x0800    /* ---- 1--- ---- ---- */
  77. #define SYSTEM        0x1000    /* ---1 ---- ---- ---- */
  78. #define BUNDLE        0x2000    /* --1- ---- ---- ---- */
  79. #define INVISIBLE    0x4000    /* -1-- ---- ---- ---- */
  80. #define LOCKED        0x8000    /* 1--- ---- ---- ---- */
  81.  
  82. #define NOMODIFY    (DESKTOP | INITED | CHANGED | BUSY)
  83.  
  84. typedef struct {
  85.     Byte    name[64];    /* File name */
  86.     short    volume;        /* Volume reference number */
  87.     long    directory;    /* Directory ID */
  88.     short    ref;        /* File reference number */
  89.     long    data;        /* Size of data fork */
  90.     long    resource;    /* Size of resource fork */
  91.     long    mark;        /* Current read/write mark */
  92.     HEADER    header;        /* MacBinary header */
  93. } MBFCB;
  94.  
  95. static MBFCB **File = 0;        /* Current file control block handle */
  96.  
  97. /* ----- Minimum ------------------------------------------------------- */
  98.  
  99. static long Minimum(register long a, register long b)
  100. {
  101.     return (a < b) ? a : b;
  102. }
  103.  
  104. /* ----- Set up MacBinary header --------------------------------------- */
  105.  
  106. static short InitMacBinary(
  107.     short volume,
  108.     long directory,
  109.     Byte *name,
  110.     HEADER *header,
  111.     long *data,
  112.     long *resource)
  113. {
  114.     short err;
  115.     unsigned short crc;
  116.     HFileParam param;
  117.  
  118.     memset(¶m, 0, sizeof(param));
  119.     param.ioNamePtr = (StringPtr)name;
  120.     param.ioVRefNum = volume;
  121.     param.ioDirID = directory;
  122.     if (err = PBHGetFInfo((HParmBlkPtr)¶m, FALSE))
  123.         return err;
  124.  
  125.     memset(header, 0, BinHeaderLength);
  126.     memcpy(&HEADER_name, name, name[0] + 1);
  127.     HEADER_info2 = param.ioFlFndrInfo.fdFlags & 0x00FF;
  128.     param.ioFlFndrInfo.fdFlags &= 0xFF00;
  129.     *(long *)¶m.ioFlFndrInfo.fdLocation = 0;
  130.     param.ioFlFndrInfo.fdFldr = 0;
  131.     memcpy(&HEADER_info1, (void *)¶m.ioFlFndrInfo, 16);
  132.     HEADER_protected = (Byte)(param.ioFlAttrib) & 0x01;
  133.     memcpy(&HEADER_dLength, (void *)¶m.ioFlLgLen, 4);
  134.     memcpy(&HEADER_rLength, (void *)¶m.ioFlRLgLen, 4);
  135.     memcpy(&HEADER_creation, (void *)¶m.ioFlCrDat, 4);
  136.     memcpy(&HEADER_modification, (void *)¶m.ioFlMdDat, 4);
  137.     HEADER_newVersion = 129;
  138.     HEADER_minimumVersion = 129;
  139.     crc = CalcCRC((Byte *)header, 124, 0);
  140.     memcpy(&HEADER_crc, (void *)&crc, 2);
  141.  
  142.     *data = param.ioFlLgLen;
  143.     *resource = param.ioFlRLgLen;
  144.     return 0;
  145. }
  146.  
  147. /* ----- Verify MacBinary header --------------------------------------- */
  148.  
  149. short BinCheckHeader(
  150.     register Byte *p,
  151.     Byte *name,                /* File name */
  152.     long *data,                /* Data fork length */
  153.     long *resource)            /* Resource fork length */
  154. {
  155.     register short i, j, version;
  156.     register HEADER *header;
  157.     unsigned short crc;
  158.  
  159.     *name = 0;
  160.     *data = *resource = 0;
  161.     header = (HEADER *)p;
  162.     if (p[0] || p[74] || p[82] || p[83] || p[87] ||
  163.             (i = HEADER_name) > 63)
  164.         return 0;
  165.     memcpy((void *)&crc, &HEADER_crc, 2);
  166.     if (crc == CalcCRC((Byte *)header, 124, 0) &&
  167.             HEADER_minimumVersion <= 129)
  168.         version = 2;
  169.     else {
  170.         for (j = 101; j < 125; j++)
  171.             if (p[j])
  172.                 return 0;
  173.         version = 1;
  174.     }
  175.     memcpy((void *)name, &HEADER_name, i + 1);
  176.     memcpy((void *)data, &HEADER_dLength, 4);
  177.     memcpy((void *)resource, &HEADER_rLength, 4);
  178.     return version;
  179. }
  180.  
  181. /* ----- Set up file info from MacBinary header ------------------------ */
  182.  
  183. static short SetupMacBinary(
  184.     HEADER *header,
  185.     short volume,
  186.     long directory,
  187.     Byte *name)
  188. {
  189.     register short err;
  190.     HFileParam param;
  191.     FInfo info;
  192.  
  193.     memset(¶m, 0, sizeof(param));
  194.     param.ioNamePtr = (StringPtr)name;
  195.     param.ioVRefNum = volume;
  196.     param.ioDirID = directory;
  197.     if (err = PBHGetFInfo((HParmBlkPtr)¶m, FALSE))
  198.         return err;
  199.  
  200.     memcpy((void *)&info, &HEADER_info1, sizeof(info));
  201.     info.fdFlags &= 0xFF00;            /* High byte */
  202.     info.fdFlags |= HEADER_info2;    /* Low byte */
  203.     info.fdFlags &= ~NOMODIFY;
  204.     param.ioFlFndrInfo.fdType = info.fdType;
  205.     param.ioFlFndrInfo.fdCreator = info.fdCreator;
  206.     param.ioFlFndrInfo.fdFlags &= NOMODIFY;
  207.     param.ioFlFndrInfo.fdFlags |= info.fdFlags;
  208.     memcpy((void *)¶m.ioFlCrDat, &HEADER_creation, 4);
  209.     memcpy((void *)¶m.ioFlMdDat, &HEADER_modification, 4);
  210.     param.ioNamePtr = (StringPtr)name;
  211.     param.ioVRefNum = volume;
  212.     param.ioDirID = directory;
  213.     return PBHSetFInfo((HParmBlkPtr)¶m, FALSE);
  214. }
  215.  
  216. /* ----- Open disk file for reading ------------------------------------ */
  217.  
  218. short BinOpenRead(
  219.     register short volume,
  220.     register long directory,
  221.     register Byte *name)
  222. {
  223.     register MBFCB **f;
  224.     register MBFCB *p;
  225.     register short err;
  226.  
  227.     if (File)
  228.         return 1;        /* Is already open! */
  229.     if (!(f = (MBFCB **)NewHandle(sizeof(MBFCB))))
  230.         return 2;        /* Memory problem! */
  231.  
  232.     HLock((Handle)f);
  233.     p = *f;
  234.     if (!(err = InitMacBinary(volume, directory, name,
  235.             &p->header, &p->data, &p->resource))) {
  236.         memcpy((void *)p->name, (void *)name, name[0] + 1);
  237.         p->volume = volume;
  238.         p->directory = directory;
  239.         p->mark = 0;
  240.     }
  241.     HUnlock((Handle)f);
  242.     if (err)
  243.         DisposHandle((Handle)f);
  244.     else
  245.         File = f;        /* Now is open */
  246.     return err;
  247. }
  248.  
  249. /* ----- Read from disk file ------------------------------------------- */
  250.  
  251. short BinRead(
  252.     long *count,
  253.     Byte *buffer)
  254. {
  255.     register MBFCB **f;
  256.     register MBFCB *p;
  257.     register short err;
  258.     register long n;
  259.     long b, c, d, e;
  260.     long i;
  261.  
  262.     if (!(f = File))
  263.         return 1;        /* Is not open! */
  264.     HLock((Handle)f);
  265.     p = *f;
  266.  
  267.     b = sizeof(HEADER) + p->data;
  268.     c = b + Filler(BinHeaderLength, p->data);
  269.     d = c + p->resource;
  270.     e = d + Filler(BinHeaderLength, p->resource);
  271.  
  272.     /* Open data fork of file if necessary */
  273.  
  274.     if (p->mark == sizeof(HEADER) &&
  275.             (err = OpenFile(p->volume,p->directory,p->name,&p->ref)))
  276.         goto done;
  277.  
  278.     /* Close data fork of file if necessary */
  279.  
  280.     if (p->mark == b) {
  281.         FSClose(p->ref);
  282.         p->ref = 0;
  283.     }
  284.  
  285.     /* Open resource fork of file if necessary */
  286.  
  287.     if (p->mark == c &&
  288.             (err = OpenResource(p->volume,p->directory,p->name,&p->ref)))
  289.         goto done;
  290.  
  291.     /* Close resource fork of file if necessary */
  292.  
  293.     if (p->mark == d) {
  294.         FSClose(p->ref);
  295.         p->ref = 0;
  296.     }
  297.  
  298.     /* Copy from header */
  299.  
  300.     if (p->mark < sizeof(HEADER)) {
  301.         n = Minimum(*count, sizeof(HEADER) - p->mark);
  302.         memcpy((void *)buffer, (Byte *)&p->header + p->mark, n);
  303.         goto allright;
  304.     }
  305.  
  306.     /* Read data fork */
  307.  
  308.     if (p->mark < b) {
  309.         i = Minimum(*count, b - p->mark);
  310.         err = FSRead(p->ref, &i, buffer);
  311.         n = i;
  312.         goto done;
  313.     }
  314.  
  315.     /* Clear buffer (fill up to entire multiple of 128 bytes) */
  316.  
  317.     if (p->mark < c) {
  318.         n = Minimum(*count, c - p->mark);
  319.         memset(buffer, 0, n);
  320.         goto allright;
  321.     }
  322.  
  323.     /* Read resource fork */
  324.  
  325.     if (p->mark < d) {
  326.         i = Minimum(*count, d - p->mark);
  327.         err = FSRead(p->ref, &i, buffer);
  328.         n = i;
  329.         goto done;
  330.     }
  331.  
  332.     /* Clear buffer (fill up to entire multiple of 128 bytes) */
  333.  
  334.     if (p->mark < e) {
  335.         n = Minimum(*count, e - p->mark);
  336.         memset(buffer, 0, n);
  337.         goto allright;
  338.     }
  339.  
  340.     /* End of file reached */
  341.  
  342.     err = eofErr;
  343.     n = 0;
  344.     goto done;
  345.  
  346. allright:
  347.     err = 0;        /* No error */
  348. done:
  349.     if (!err) {
  350.         p->mark += n;
  351.         if (c = *count - n)
  352.             err = BinRead(&c, buffer + n);
  353.         *count = n + c;
  354.     } else {
  355.         if (err == eofErr) {
  356.             p->mark += n;
  357.             *count = n;
  358.         }
  359.     }
  360.  
  361.     HUnlock((Handle)f);
  362.     return err;
  363. }
  364.  
  365. /* ----- Close disk file after reading --------------------------------- */
  366.  
  367. short BinCloseRead(void)
  368. {
  369.     register short ref;
  370.  
  371.     if (!File)
  372.         return 1;                /* Is not open! */
  373.     if (ref = (**File).ref)
  374.         FSClose(ref);            /* Data or resource fork */
  375.     DisposHandle((Handle)File);
  376.     File = 0;                    /* Now file is closed */
  377.     return 0;
  378. }
  379.  
  380. /* ----- Open disk file for writing ------------------------------------ */
  381.  
  382. short BinOpenWrite(
  383.     register short volume,
  384.     register long directory,
  385.     register Byte *name,
  386.     register Byte *header)
  387. {
  388.     register MBFCB **f;
  389.     register MBFCB *p;
  390.     Byte name2[64];
  391.  
  392.     if (File)
  393.         return 1;        /* Is already open! */
  394.  
  395.     if (!(f = (MBFCB **)NewHandle(sizeof(MBFCB))))
  396.         return 2;        /* Memory problem! */
  397.  
  398.     HLock((Handle)f);
  399.     p = *f;
  400.  
  401.     BinCheckHeader(header, name2, &p->data, &p->resource);
  402.     memcpy((void *)&p->header, (void *)header, sizeof(HEADER));
  403.     memcpy((void *)p->name, (void *)name, name[0] + 1);
  404.     p->volume = volume;
  405.     p->directory = directory;
  406.     p->mark = sizeof(HEADER);
  407.  
  408.     HUnlock((Handle)f);
  409.     File = f;            /* Now is open */
  410.     return 0;
  411. }
  412.  
  413. /* ----- Write to disk file -------------------------------------------- */
  414.  
  415. short BinWrite(
  416.     long *count,
  417.     Byte *buffer)
  418. {
  419.     register MBFCB **f;
  420.     register MBFCB *p;
  421.     register short err;
  422.     register long n;
  423.     long b, c, d, e;
  424.     long i;
  425.  
  426.     if (!(f = File))
  427.         return 1;        /* Is not open! */
  428.     HLock((Handle)f);
  429.     p = *f;
  430.  
  431.     b = sizeof(HEADER) + p->data;
  432.     c = b + Filler(BinHeaderLength, p->data);
  433.     d = c + p->resource;
  434.     e = d + Filler(BinHeaderLength, p->resource);
  435.  
  436.     /* Open data fork of file if necessary */
  437.  
  438.     if (p->mark == sizeof(HEADER) &&
  439.             (err = OpenFile(p->volume,p->directory,p->name,&p->ref)))
  440.         goto done;
  441.  
  442.     /* Close data fork of file if necessary */
  443.  
  444.     if (p->mark == b) {
  445.         FSClose(p->ref);
  446.         p->ref = 0;
  447.     }
  448.  
  449.     /* Open resource fork of file if necessary */
  450.  
  451.     if (p->mark == c &&
  452.             (err = OpenResource(p->volume,p->directory,p->name,&p->ref)))
  453.         goto done;
  454.  
  455.     /* Close resource fork of file if necessary */
  456.  
  457.     if (p->mark == d) {
  458.         FSClose(p->ref);
  459.         p->ref = 0;
  460.     }
  461.  
  462.     /* Ignore header */
  463.  
  464.     if (p->mark < sizeof(HEADER)) {
  465.         n = Minimum(*count, sizeof(HEADER) - p->mark);
  466.         goto allright;
  467.     }
  468.  
  469.     /* Write data fork */
  470.  
  471.     if (p->mark < b) {
  472.         i = Minimum(*count, b - p->mark);
  473.         err = FSWrite(p->ref, &i, buffer);
  474.         n = i;
  475.         goto done;
  476.     }
  477.  
  478.     /* Ignore buffer (filled up to entire multiple of 128 bytes) */
  479.  
  480.     if (p->mark < c) {
  481.         n = Minimum(*count, c - p->mark);
  482.         goto allright;
  483.     }
  484.  
  485.     /* Write resource fork */
  486.  
  487.     if (p->mark < d) {
  488.         i = Minimum(*count, d - p->mark);
  489.         err = FSWrite(p->ref, &i, buffer);
  490.         n = i;
  491.         goto done;
  492.     }
  493.  
  494.     /* Ignore buffer (filled up to entire multiple of 128 bytes) */
  495.  
  496.     if (p->mark < e) {
  497.         n = Minimum(*count, e - p->mark);
  498.         goto allright;
  499.     }
  500.  
  501.     /* End of file reached (can happen if using XModem 1K) */
  502.  
  503.     err = eofErr;
  504.     n = 0;
  505.     goto done;
  506.  
  507. allright:
  508.     err = 0;        /* No error */
  509. done:
  510.     if (!err) {
  511.         p->mark += n;
  512.         if (c = *count - n)
  513.             err = BinWrite(&c, buffer + n);
  514.         *count = n + c;
  515.     } else {
  516.         if (err == eofErr) {
  517.             p->mark += n;
  518.             *count = n;
  519.             err = noErr;
  520.         }
  521.     }
  522.  
  523.     HUnlock((Handle)f);
  524.     return err;
  525. }
  526.  
  527. /* ----- Close disk file after writing --------------------------------- */
  528.  
  529. short BinCloseWrite(void)
  530. {
  531.     register short err;
  532.     register MBFCB **f;
  533.     register MBFCB *p;
  534.  
  535.     if (!(f = File))
  536.         return 1;                /* Is not open! */
  537.     HLock((Handle)f);
  538.     p = *f;
  539.     err = SetupMacBinary((HEADER *)&p->header, p->volume, p->directory,
  540.         p->name);
  541.     if (p->ref)
  542.         FSClose(p->ref);        /* Data or resource fork */
  543.     FlushVol(0, p->volume);
  544.     HUnlock((Handle)f);
  545.     DisposHandle((Handle)f);
  546.     File = 0;                    /* Now file is closed */
  547.     return err;
  548. }
  549.  
  550. /* ----- Get length of complete MacBinary file ------------------------- */
  551.  
  552. short BinGetEOF(register long *eof)
  553. {
  554.     register MBFCB **f;
  555.     register MBFCB *p;
  556.  
  557.     *eof = 0;
  558.     if (!(f = File))
  559.         return 1;                /* Is not open! */
  560.     p = *f;
  561.     *eof = BinHeaderLength +
  562.         p->data + Filler(BinHeaderLength, p->data) +
  563.         p->resource + Filler(BinHeaderLength, p->resource);
  564.     return 0;
  565. }
  566.